/*================================================================
*   Copyright (C) 2023 baichao All rights reserved.
*
*   文件名称：status.cpp
*   创 建 者：baichao
*   创建日期：2023年11月24日
*   描    述：
*
================================================================*/

#include "status.h"

#include <cstring>
#include <cstdio>

Status::Status(const Status &rhs) : state_(CopyState(rhs.state_)) {}

Status &Status::operator=(const Status &rhs)
{
    if (this != &rhs)
    {
        delete[] state_;
        state_ = CopyState(rhs.state_);
    }
    return *this;
}

Status::Status(Status &&rhs) : state_(rhs.state_)
{
    rhs.state_ = nullptr;
}

Status &Status::operator=(Status &&rhs)
{
    if (this != &rhs)
    {
        delete[] state_;
        state_ = rhs.state_;
        rhs.state_ = nullptr;
    }
    return *this;
}

Status Status::NotFound(const char *msg)
{
    return Status(kNotFound, msg);
}

Status Status::Corruption(const char *msg)
{
    return Status(kCorruption, msg);
}

Status Status::NotSupported(const char *msg)
{
    return Status(kNotSupported, msg);
}

Status Status::InvalidArgument(const char *msg)
{
    return Status(kInvalidArgument, msg);
}

Status Status::IOError(const char *msg)
{
    return Status(kIOError, msg);
}

Status::Status(Code code, const char *msg)
{
    const int len = strlen(msg);
    const int size = len + 5;
    char *result = new char[size];
    memcpy(result + 5, msg, len);
    memcpy(result, &size, 4);
    result[4] = static_cast<char>(code);
    state_ = result;
}

bool Status::IsNotFound() const
{
    return code() == kNotFound;
}

bool Status::IsCorruption() const
{
    return code() == kCorruption;
}

bool Status::IsIOError() const
{
    return code() == kIOError;
}

bool Status::IsNotSupportedError() const
{
    return code() == kNotSupported;
}

bool Status::IsInvalidArgument() const
{
    return code() == kInvalidArgument;
}

std::string Status::ToString() const
{
    if (state_ == nullptr)
    {
        return "OK";
    }
    else
    {
        std::string result;
        const int len = *((int *)state_) - 5;
        const char code = *(state_ + 4);
        switch (code)
        {
        case kNotFound:
            result += "NotFound: ";
            break;
        case kCorruption:
            result += "Corruption: ";
            break;
        case kNotSupported:
            result += "Not supported: ";
            break;
        case kInvalidArgument:
            result += "Invalid argument: ";
            break;
        case kIOError:
            result += "I/O error: ";
            break;
        default:
            result += "Unknown code: " + code;
            break;
        }

        result.append(state_ + 5, len);
        return result;
    }
}

char *Status::CopyState(const char *state)
{
    const int size = *((int *)state);
    char *result = new char[size];
    memcpy(result, state, size);
    return result;
}
